<?php
namespace app\data\command;
use think\admin\Command;
use think\admin\Exception;
use think\console\Input;
use think\console\Output;
use think\console\input\Argument;
use think\console\input\Option;
use think\admin\service\ProcessService;
use think\facade\Db;
use Stomp\Client;
use Stomp\Network\Observer\Exception\HeartbeatException;
use Stomp\Network\Observer\ServerAliveObserver;
use Stomp\StatefulStomp;
use app\data\service\IotMsgService;
/**
 * 阿里云服务端订阅消息
 * Class AliyunIot
 * @package app\data\command
 * nohup php think Aliyun:AliyunIot &  守护
 *  ps -ef | grep php 查询端口
 * kill -9 xxxx 删除端口
 */
class AliyunIot extends Command
{
    protected $name = 'Aliyun:AliyunIot';
    protected function configure()
    {
        $this->setName($this->name);
        $this->setDescription('阿里云服务端订阅消息');
    }
    /**
     * 业务指令执行
     * @param Input $input
     * @param Output $output
     * @return void
     * @throws Exception
     */
    protected function execute(Input $input, Output $output)
    {
        $this->begin();
    }

    protected function begin(){
        $accessKey = config('iot.accessKeyId');
        $accessSecret =  config('iot.accessKeySecret');
        $consumerGroupId = "DEFAULT_GROUP";
        $clientId = "your_milk";
        $iotInstanceId = config('iot.IotInstanceId');//iotInstanceId：实例ID。
        $timeStamp = round(microtime(true) * 1000);
        $signMethod = "hmacsha1";//签名方法
        $userName = $clientId . "|authMode=aksign"
            . ",signMethod=" . $signMethod
            . ",timestamp=" . $timeStamp
            . ",authId=" . $accessKey
            . ",iotInstanceId=" . $iotInstanceId
            . ",consumerGroupId=" . $consumerGroupId
            . "|";
        $signContent = "authId=" . $accessKey . "&timestamp=" . $timeStamp;
//计算签名，password组装方法，请参见AMQP客户端接入说明文档。
        $password = base64_encode(hash_hmac("sha1", $signContent, $accessSecret, $raw_output = TRUE));
//接入域名，请参见AMQP客户端接入说明文档。
        $client = new Client( config('iot.amqp_url'));
        $sslContext = ['ssl' => ['verify_peer' => true, 'verify_peer_name' => false],];
        $client->getConnection()->setContext($sslContext);

//服务端心跳监听。
        $observer = new ServerAliveObserver();
        $client->getConnection()->getObservers()->addObserver($observer);
//心跳设置，需要云端每30s发送一次心跳包。
        $client->setHeartbeat(0, 30000);
        $client->setLogin($userName, $password);
        try {
            $client->connect();
        } catch (StompException $e) {
            echo "failed to connect to server, msg:" . $e->getMessage(), PHP_EOL;
        }
//无异常时继续执行。
        $stomp = new StatefulStomp($client);
        $stomp->subscribe('/topic/#');
        echo "connect success";
        while (true) {
            try {
                // 检查连接状态
                if (!$client->isConnected()) {
                    echo "connection not exists, will reconnect after 10s.", PHP_EOL;
                    sleep(10);
                    $client->connect();
                    $stomp->subscribe('/topic/#');
                    echo "connect success", PHP_EOL;
                }
                //echo $stomp->read();
                //处理消息业务逻辑。
                $msg = $stomp->read();
                if($msg){
                    //var_dump($msg);
                    $msgService = new IotMsgService();
                    $msgService->handle($msg->getCommand(),$msg->getHeaders(),$msg->getBody());

                }
                // $this->log_result($msg);
                // echo $stomp->read();
            } catch (HeartbeatException $e) {
                echo 'The server failed to send us heartbeats within the defined interval.', PHP_EOL;
                $stomp->getClient()->disconnect();
            } catch (Exception $e) {
                echo 'process message occurs error: ' . $e->getMessage(), PHP_EOL;
                $stomp->getClient()->disconnect();
            }
        }
    }
    protected function log_result($word)
    {
        @($fp = fopen("log.txt", "a"));
        @flock($fp, LOCK_EX);
        @fwrite($fp, $word. "\r\n");
        @flock($fp, LOCK_UN);
        @fclose($fp);
    }

}